//package org.ddd.pattern.event.consumer.retry;
//
//
//import lombok.extern.slf4j.Slf4j;
//import org.ddd.pattern.event.consumer.interceptor.tt.SubscriberFactory;
//import org.ddd.pattern.event.domain.annotation.RetryRule;
//import org.ddd.pattern.event.domain.enums.ExecutionStatus;
//import org.ddd.pattern.event.domain.exception.DomainEventException;
//
//import java.lang.reflect.Method;
//import java.util.Map;
//import java.util.Objects;
//import java.util.Optional;
//import java.util.concurrent.ConcurrentHashMap;
//
//@Slf4j
//public class RetryRuleSubscribeHandler implements ISubscribeHandler {
//
//    private final IRetryRuleResolver retryRuleResolver;
//
//    public RetryRuleSubscribeHandler(IRetryRuleResolver retryRuleResolver) {
//        this.retryRuleResolver = retryRuleResolver;
//    }
//
//    public RetryRuleSubscribeHandler() {
//        retryRuleResolver = new DefaultRetryRuleResolver();
//    }
//
//    private static final Map<String, RetryRecord> RETRY_RECORDS = new ConcurrentHashMap<>();
//
//
//    public static class RetryRecord {
//        private int retryCount;
//        private int retryInterval;
//        private int currRetryCount = 0;
//        private int currRetryInterval = 0;
//        private RetryType retryType;
//
//
//        public RetryRecord(int retryCount, int retryInterval, RetryType retryType) {
//            this.retryCount = retryCount;
//            this.retryInterval = retryInterval;
//            this.retryType = retryType;
//        }
//
//        public boolean canRetry() {
//            return (retryType == RetryType.ALWAYS
//                    || (retryType == RetryType.CUSTOM && retryCount >= currRetryCount))
//                    && currRetryInterval % retryInterval == 0;
//        }
//
//        public void addRetryCount() {
//            currRetryInterval += 1;
//            if (currRetryInterval % retryInterval == 0) {
//                currRetryCount += 1;
//            }
//        }
//
//        public void initRetryCount() {
//            currRetryCount = 0;
//            currRetryInterval = 0;
//        }
//
//        @Override
//        public String toString() {
//            return "RetryRecord{" +
//                    "retryCount=" + retryCount +
//                    ", retryInterval=" + retryInterval +
//                    ", currRetryCount=" + currRetryCount +
//                    ", currRetryInterval=" + currRetryInterval +
//                    ", retryType=" + retryType +
//                    ", canRetry=" + canRetry() +
//                    '}';
//        }
//    }
//
//
//    @Override
//    public void handle(ISubscribeRequest request, ISubscribeResponse response,
//                       ISubscribeHandlerChain chain) {
//
//        final Optional<Method> method = SubscriberFactory.cacheSubscribeMethodFor(request.getHandler(), request);
//        RetryRule retryRule = method.map(value -> value.getAnnotation(RetryRule.class)).orElse(null);
//        if (retryRule == null) {
//            retryRule = request.getHandler().getClass() .getAnnotation(RetryRule.class);
//        }
//
//        if (Objects.isNull(retryRule)) {
//            chain.handle(request, response);
//            return;
//        }
//
//        final RetryRuleInfo retryRuleInfo = retryRuleResolver.resolve(retryRule);
//        final RetryType retryType = retryRuleInfo.getRetryType();
//        final int retryInterval = retryRuleInfo.getRetryInterval();
//        final int retryCount = retryRuleInfo.getRetryCount();
//        final RocketMsgMetadata messageInfo = request.getMessageContext().getMessageInfo();
//        final String consumerGroup = messageInfo.getConsumerGroup();
//        final String topic = messageInfo.getTopic();
//        final String subTopic = messageInfo.getSubTopic();
//        String retryKey = String.format("%s-%s-%s-%s", consumerGroup, topic, subTopic,request.getMessageContext().getMessageInfo().getMessageKey());
//        RetryRecord retryRecord = RETRY_RECORDS.putIfAbsent(retryKey, new RetryRecord(retryCount, retryInterval, retryType));
//        if (retryRecord == null || retryRecord.canRetry()) {
//            retryRecord = RETRY_RECORDS.get(retryKey);
//            retryRecord.addRetryCount();
//
//            chain.handle(request, response);
//            final ISubscribeResult subscribeResult = response.getSubscribeResult();
//            if (subscribeResult.getExecutionStatus() == ExecutionStatus.SUCCESS
//                    || subscribeResult.getExecutionStatus() == ExecutionStatus.RECONSUME_ERROR) {
//                retryRecord.initRetryCount();
//            }
//        } else {
//            response.setSubscribeResult(SubscribeResult.FAILURE(new DomainEventException("消息重试已达最大上限")));
//            log.warn("【领域事件】事件重试已达最大上限! consumer_group->{}, topic->{}, tag->{}, key->{}"
//                    , consumerGroup, topic, subTopic, messageInfo.getMessageKey());
//        }
//
//    }
//
//    @Override
//    public int order() {
//        return 10;
//    }
//}
